﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Flame.Controls.Common;
using Flame.Dlr;
using Flame.Reflection;

namespace Flame.Controls
{
    public abstract class ATextInput //: ITextInput
    {

        public abstract int CurrentPos { get; set; }
        public abstract int CaretOnScreenPosY { get; }
        public abstract int ContentHeight { get; }
        public abstract int caret_LineNumber { get; }
        public abstract int lines_Count { get; }
        public abstract string selection_Text { get; }
        public abstract string lines_Current_Text { get; }
        public abstract Control Control { get; }
        public abstract IAutocomplete IAutocomplete { get; }
        public abstract ICallTip ICallTip { get; }
        
        
        //protected abstract void onAutoStartChanged();
        protected abstract void onLanguageChanged();

        public virtual event EventHandler GotFocus;
        public virtual event System.Windows.Forms.KeyEventHandler KeyDown;
        public virtual event EventHandler AskForFocusToPrevious;
        public virtual event EventHandler AskForFocusToNext;
        public virtual event EventHandler OnMoveCaretOnScreen;
        public virtual event EventHandler OnResizeHeight;
        public virtual event EventHandler<CompilerResultEventArgs> OnCompile;
        public virtual event EventHandler<LanguageChangedEventArgs> OnLanguageChanged;
        public virtual event EventHandler<AutoStartChangedEventArgs> OnAutoStartChanged;
        public virtual event EventHandler<System.Windows.Forms.MouseEventArgs> MouseWheelFromChilds;


        
        bool _autostart;
        Type _language;
        protected IExecEngines _compilers;



        public ATextInput(IExecEngines compilers)
        {

            _language = Languages.None;
            AutoStart = false;
            _compilers = compilers;
            setEvents();
        }
        public ATextInput()
        {
        }


        void setEvents()
        {
            Control.GotFocus += (s, e) => { if (GotFocus != null) GotFocus(s, e); };
            Control.TextChanged += (sender, e) => { if (Control.Text != "") { OnResizeHeight(sender, e); } };
            Control.MouseWheel += (sender, e) => { if (MouseWheelFromChilds != null) MouseWheelFromChilds(sender, e); };
            Control.KeyDown += (sender, e) =>
            {
                if (KeyDown != null) KeyDown(sender, e);
                if (e.Control && !e.Alt && e.Shift && e.KeyCode == Keys.Enter)
                {
                    if (selection_Text.Length == 0)
                        _compilers.Execute(Language, lines_Current_Text);
                    else
                        _compilers.Execute(Language, selection_Text);
                    e.SuppressKeyPress = true;
                    return;
                }
                else if (!e.Control && !e.Alt && e.Shift && e.KeyCode == Keys.Enter)
                {
                    Compile();
                    e.SuppressKeyPress = true;
                    AskForFocusToNext(sender, e);
                    OnMoveCaretOnScreen(sender, e);
                    OnResizeHeight(sender, e);
                    return;
                }
                else if (!e.Control && e.Alt && !e.Shift && (e.KeyCode == Keys.PageUp || e.KeyCode == Keys.PageDown))
                {
                    if (OnMoveCaretOnScreen != null)
                    {
                        OnMoveCaretOnScreen(sender, e);
                    }
                }
                /*else if (e.Control && e.Shift && e.Alt && e.KeyCode == Keys.P)
                {
                    Language = Languages.Python;
                }
                else if (e.Control && e.Shift && e.Alt && e.KeyCode == Keys.R)
                {
                    Language = Languages.Ruby;
                }
                else if (e.Control && e.Shift && e.Alt && e.KeyCode == Keys.S)
                {
                    Language = Languages.Powershell;
                }
                else if (e.Control && e.Shift && e.Alt && e.KeyCode == Keys.C)
                {
                    Language = Languages.CSharp;
                }
                else if (e.Control && e.Shift && e.Alt && e.KeyCode == Keys.K)
                {
                    Language = Languages.CSharpScript;
                }
                else if (e.Control && e.Shift && e.Alt && e.KeyCode == Keys.J)
                {
                    Language = Languages.Javascript;
                }
                else if (e.Control && e.Shift && e.Alt && e.KeyCode == Keys.A)
                {
                    AutoStart = !AutoStart;
                }*/
                else if (e.Control && !e.Alt && !e.Shift && e.KeyCode == Keys.Space)
                {
                    e.Handled = true;
                    e.SuppressKeyPress = true;
                    IAutocomplete.TryShow();
                }
                else if (!e.Control && !e.Alt && !e.Shift && (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down))
                {

                    if (e.KeyCode == Keys.Up)
                    {
                        if (ICallTip.IsActive)
                        {
                            uint x;
                            if (ICallTip.IOverloadList.CurrentIndex == 0)
                                x = (uint)ICallTip.IOverloadList.Count - 1;
                            else
                                x = (uint)ICallTip.IOverloadList.CurrentIndex - 1;

                            ICallTip.ShowOverload(-1, x, -1, -1);
                            e.SuppressKeyPress = true;
                            return;
                        }
                        if (IAutocomplete.IsActive) return;
                        if (caret_LineNumber == 0)
                        {
                            AskForFocusToPrevious(sender, e);
                        }
                    }
                    else
                    {
                        if (ICallTip.IsActive)
                        {
                            uint x;
                            if (ICallTip.IOverloadList.CurrentIndex == ICallTip.IOverloadList.Count - 1)
                                x = 0;
                            else
                                x = (uint)ICallTip.IOverloadList.CurrentIndex + 1;
                            ICallTip.ShowOverload(-1, x, -1, -1);
                            e.SuppressKeyPress = true;
                            return;
                        }

                        if (IAutocomplete.IsActive) return;
                        if (caret_LineNumber == lines_Count - 1)
                        {
                            AskForFocusToNext(sender, e);
                        }
                    }

                    if (OnMoveCaretOnScreen != null)
                    {
                        OnMoveCaretOnScreen(sender, e);
                    }

                }
                else if (!e.Control && e.Alt && !e.Shift && (e.KeyCode == Keys.PageUp || e.KeyCode == Keys.PageDown))
                {
                    if (ICallTip.IsActive) return;
                    if (IAutocomplete.IsActive) return;

                    if (e.KeyCode == Keys.PageUp)
                    {

                        AskForFocusToPrevious(sender, e);

                    }
                    else
                    {
                        AskForFocusToNext(sender, e);

                    }

                    e.Handled = true;

                }
            };
        }


        /*public string LanguageName
        {
            set
            {
                Language = _compilers.GetEngine(value).GetType();
            }
        }*/
        public virtual Type Language
        {
            get { return _language; }
            set
            {
                _language = value;
                IAutocomplete.CurrentLanguage = _language;
                onLanguageChanged();
                if (OnLanguageChanged != null)
                    OnLanguageChanged(this, new LanguageChangedEventArgs(value));
            }
        }
        public virtual string Text { get { return Control.Text; } set { Control.Text = value; } }
        public virtual bool Focused { get { return Control.Focused; } }
        public virtual bool Focus() { return Control.Focus(); }

        public virtual void Compile() { OnCompile(this, new CompilerResultEventArgs(_compilers.Execute(Language, Text))); }
        public virtual bool AutoStart
        {
            get { return _autostart; }
            set
            {
                _autostart = value;
                //onAutoStartChanged();
                if (OnAutoStartChanged != null)
                    OnAutoStartChanged(this, new AutoStartChangedEventArgs(value));
            }
        }
        public virtual void SetParent(System.Windows.Forms.Panel panel)
        {
            Control.Dock = DockStyle.Fill;
            panel.Controls.Add(Control);
        }

        

    }
}
